package net.apexcns.core.util;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

//import net.apexcns.test.util.TestUtil;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.log4j.Logger;


public class BeanUtil extends BeanUtils {
	private static Logger logger = Logger.getLogger(BeanUtil.class);

	/** underscore 를 camel case 로 */
	// camel 인 경우?
	public static String convUnderToCamel(String cn) {
		StringBuffer sb = new StringBuffer();
		String[] str = cn.split("_");
		if(str.length==1) return cn;
		boolean firstTime = true;
		for (String temp : str) {
			if (firstTime) {
				sb.append(temp.toLowerCase());
				firstTime = false;
			} else {
				sb.append(Character.toUpperCase(temp.charAt(0)));
				sb.append(temp.substring(1).toLowerCase());
			}
		}
		return sb.toString();
	}
	
	/** CLI 결과를 bean으로 매핑<pre>
	 * text ="
	 * hw_caps                : bfebfbff:28100800:00000000
	 * virt_caps              : hvm"
	 * BeanUtil.convCliTextToBean(bean, text, "[\r\n]", ":");</pre>
	 */
	public static void convCliTextToBean(Object bean, String text, String lineChar, String delim) {
		if(text == null) return;
		String[] lineArr = text.split(lineChar);
		for(String line : lineArr) {
			String[] dataArr = StringUtil.splitTwoWords(line, delim);
			try {
				BeanUtils.setProperty(bean
						, BeanUtil.convUnderToCamel(dataArr[0]).trim(), dataArr[1].trim());
			} catch (Exception e) {
				logger.debug(e.getMessage());
			}
		}
	}

	/** Map.toString()에서 {,}가 빠진 형태의 텍스트를 bean으로 매핑<pre>
	 * text ="hw_caps=bfebfbff:28100800:00000000, virt_caps=hvm";
	 * BeanUtil.convMapTextToBean(bean, text);</pre>
	 */
	// TODO :key=val,ue, key2=value2 
	public static void convMapTextToBean(Object bean, String text) {
		convCliTextToBean(bean, text, ",", "=");
	}

	/** bean을 Map.toString()에서 {,}가 빠진 형태의 텍스트로 변환<pre>
	 * 
	 * text ="hw_caps=bfebfbff:28100800:00000000, virt_caps=hvm";
	 * BeanUtil.convMapTextFromBean(bean, text);</pre>
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static String convMapTextFromBean(Object bean, Set<String> incExcMap, boolean isInclude) {
		// TODO isInclude 처리
		Map map = new HashMap();
		StringBuilder strb = new StringBuilder();
		try {
			if(incExcMap==null) incExcMap = new HashSet<String>();
			Map beanMap = BeanUtil.describe(bean);
			if(isInclude) {
				for(Iterator<String> it = incExcMap.iterator(); it.hasNext();) {
					String key = it.next();
					if(!beanMap.containsKey(key)) continue;
					map.put(key, beanMap.get(key));
				}
			} else {
				for(Iterator<Map.Entry<String,Object>> it = beanMap.entrySet().iterator(); it.hasNext();) {
					Map.Entry<String,Object> me = it.next();
					String key = me.getKey();
					if(incExcMap.contains(key)) continue;
					map.put(key, beanMap.get(key));
				}
			}
			for(Iterator<Map.Entry<String,Object>> it = map.entrySet().iterator(); it.hasNext();) {
				Map.Entry<String,Object> me = it.next();
				strb.append(me.getKey() + "=" + StringUtil.nvl(me.getValue()));
				if(it.hasNext()) strb.append(",");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return strb.toString();
	}

	public static String convMapTextFromBean(Object bean) {
		Set<String> incExcMap = new HashSet<String>();
		incExcMap.add("class");
		incExcMap.add("logger");
		return convMapTextFromBean(bean, incExcMap, false);
	}

	// 같은경우, 첫문자를 소문자로, _ 변환후 대소처리
	//

	/** 디버그 용 */
	public static String toStringDebug(Object bean) {
		if(!logger.isDebugEnabled()) return null;
		try {
			return BeanUtils.describe(bean).toString();
		} catch (Exception e) {
			logger.debug(e.getMessage());
		}
		return null;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static Map mergeToMap(Object ... beans) {
		Map map = new HashMap();
		if(beans == null) return map;
		for(int i=beans.length-1; i>=0; i--) {
			try {
				map.putAll(BeanUtil.describe(beans[i]));
			} catch (Exception e) {
				logger.warn(e.getMessage());
			}
		}
		return map;
	}

	public static void main(String[] args) {
//		TestUtil.configWeb();
//		TbVmVo vo = new TbVmVo();
//		vo.setBoot("a");
//		System.out.println(toStringDebug(vo));
//		String ret = convMapTextFromBean(vo);
//		System.out.println(ret);

	}

}
